package com.iteaj.iot.client.modbus.message;

import com.iteaj.iot.client.ClientMessage;
import com.iteaj.iot.client.IotClientBootstrap;
import com.iteaj.iot.client.modbus.ModbusCode;
import com.iteaj.iot.utils.ByteUtil;

/**
 *  标准的modbus tcp报文协议格式
 *
 *  读请求报文格式：
 *  |             MBAP            |     MODBUS RTU
 *   00 00  00 00  00 06    FF      03    00 01  00 00
 *  | 事务 |协议标识| 长度 | 单元标识 |功能码|起始地址|寄存器数量|
 *  |               header       |         body         |
 *
 *  读响应报文格式：
 *   00 00  00 00  00 06     FF     03      01     00 00
 *  | 事务 |协议标识| 长度 | 单元标识 |功能码|字节个数|请求的数据|
 *  |               header       |         body         |
 *
 *  写请求报文格式：
 *  |             MBAP            |     MODBUS RTU
 *   00 00  00 00  00 06    FF      06    00 00  00 00      00 00   ...
 *  | 事务 |协议标识| 长度 | 单元标识 |功能码|起始地址|寄存器数量| 正文长度 | 正文 |
 *  |               header             |              body              |
 *
 *  写响应报文格式：
 *  |             MBAP            |     MODBUS RTU
 *   00 00  00 00  00 06    FF      06    00 00  00 00
 *  | 事务 |协议标识| 长度 | 单元标识 |功能码|起始地址|寄存器数量|
 *  |               header             |       body     |
 *
 * 事务处理标识：	可以理解为报文的序列号，一般每次通信之后就要加1以区别不同的通信数据报文
 * 协议标识符：	00 00表示ModbusTCP协议
 * 长度：	    表示接下来的数据长度，单位为字节
 * 单元标识符：	可以理解为设备地址
 *
 * 功能码 含义	   功能码	    含义
 * 0x01	读线圈	    0x04	读输入寄存器
 * 0x05	写单个线圈	0x03	读保持寄存器
 * 0x0F	写多个线圈	0x06	写单个保持寄存器
 * 0x02	读离散量输入	0x10	写多个保持寄存器
 *
 * 详细资料：{@code https://www.cnblogs.com/ioufev/articles/10830028.html}
 * @see ModbusCode
 * @see com.iteaj.iot.client.modbus.ModbusTcpClient
 * @see com.iteaj.iot.client.modbus.ModbusTcpClientComponent
 */
public abstract class ModbusTcpMessage extends ClientMessage {

    public ModbusTcpMessage(byte[] message) {
        super(message);
    }

    /**
     * modbus服务响应的报文的报文头
     * @param message
     * @return
     */
    @Override
    protected ModbusTcpHeader doBuild(byte[] message) {
        this.messageBody = ModbusTcpBody.buildResponseBody(message);
        return ModbusTcpHeader.buildResponseHeader(message);
    }

    @Override
    public String getMessageId() {
        return getHead().getMessageId();
    }

    @Override
    public ModbusTcpBody getBody() {
        return (ModbusTcpBody) super.getBody();
    }

    @Override
    public ModbusTcpHeader getHead() {
        return (ModbusTcpHeader) super.getHead();
    }
}
